package cn.wizzer.app.sys.modules.services.impl;

import cn.wizzer.app.sys.modules.models.SysCurrency;
import cn.wizzer.app.sys.modules.services.SysCurrencyService;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.util.HttpUtil;
import com.alibaba.dubbo.config.annotation.Service;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@IocBean(args = {"refer:dao"})
@Service(interfaceClass = SysCurrencyService.class)
public class SysCurrencyServiceImpl extends BaseServiceImpl<SysCurrency> implements SysCurrencyService {

    static Pattern trs = Pattern.compile("<tr>" +
            "\n.*?<td.*?" +
            "\n.*?<td.*?from=USD.*?" +
            "\n.*?<td.*?to=USD.*?" +
            "\n.*?");

    static Pattern tds = Pattern.compile("<td.*?</td>");

    static Pattern tetherRate = Pattern.compile("<td>1 Tether</td>\r\n" +
            "\\s+<td align=\"center\" class=\"no-padding-left\">=</td>\r\n" +
            "\\s+<td>.*? US Dollar</td>");

    private static final Log log = Logs.get();

    public SysCurrencyServiceImpl(Dao dao) {
        super(dao);
    }

    @Override
    public SysCurrency getById(String id) {
        return this.fetch(id);
    }

    @Override
    public List<SysCurrency> getAll() {
        return this.query(Cnd.where("delFlag", "=", 0).and("disabled", "=", 0).asc("sort"));
    }

    @Override
    public void refreshRate() throws IOException {
        Map<String, String> rates = new HashMap<>();
        String body = HttpUtil.createRequest()
                .setUrl("https://x-rates.com/table/?from=USD&amount=1")
                .setTimeOut(5000)
                .send()
                .getBody();
        //region 截取所需数据
        Matcher trMatcher = trs.matcher(body);
        while (trMatcher.find()) {
            String tr = trMatcher.group();
            Matcher tdMatcher = tds.matcher(tr);
            //region three tds[name,USD2this,this2USD]
            if(tdMatcher.find() && tdMatcher.find()){
                String secondLine = tdMatcher.group();
                String currencyName = secondLine.replaceFirst("<td.*?><a href=.*?to=", "").replaceFirst("'>.*?</a></td>", "");
                if (tdMatcher.find()) {
                    String toRate = tdMatcher.group().replaceFirst("<td.*?><a.*?>", "").replaceFirst("</a>.*?</td>", "");
                    //endregion
                    rates.put(currencyName, toRate);
                } else {
                    log.error("爬取法币("+ currencyName +")汇率失败，正则匹配不到，body:" + secondLine);
                }

            } else {
                log.error("爬取法币汇率失败，正则匹配不到，body:" + body);
            }
        }
        //endregion
        // 更新数据入库
        this.query().forEach(currency -> {
            String name = currency.getName();
            String rate = rates.get(name);
            //未获取到的数据防止插null
            if (Strings.isNotBlank(rate)) {
                log.info("更新币种汇率。币种："+ currency.getName() + "，爬到的汇率：" + rate + "，原汇率：" + currency.getRate());
                currency.setRate(new BigDecimal(rate).setScale(6, RoundingMode.FLOOR));
                this.update(currency);
            }
        });
        //region 更新USDT与美元汇率
        body = HttpUtil.createRequest()
                .setUrl("https://walletinvestor.com/converter/tether/usd/1")
                .send(HttpUtil.HTTP_METHOD.GET)
                .getBody();
        body = body.substring(body.lastIndexOf("<tbody>", body.lastIndexOf("</tbody>")));
        Matcher matcher = tetherRate.matcher(body);
        if(matcher.find()){
            String rateStr = matcher.group();
            rateStr = rateStr.substring(rateStr.lastIndexOf("<td>"),rateStr.indexOf("US")).replace("<td>", "").trim();
            if (Strings.isNotBlank(rateStr)) {
                SysCurrency usdt = this.fetch(Cnd.where("id", "=", "erc20"));
                usdt.setRate(new BigDecimal(rateStr).setScale(6, RoundingMode.FLOOR));
                this.update(usdt);
            }
        }
        else {
            log.error("爬取USDT汇率失败，正则匹配不到，body：" + body);
        }

        //endregion


    }

}
